#ifndef __CONNECTIONS_CONNECTION_H__
#define __CONNECTIONS_CONNECTION_H__

#include <functional>

#include "locations/error_codes.h"
#include "net/connection.h"

#include "utils/signals.h"

class Location;

typedef boost::signals2::signal<void (std::shared_ptr<Location>)> sig_location;
typedef sig_location::slot_type sig_location_slot;

class Location {
	friend class LocationsMgr;

public:
	typedef std::shared_ptr<Location> ptr;
	typedef std::shared_ptr<const Location> const_ptr;

	/** Build location with new connection */
	Location( const std::string& name , Connection* conn = NULL );

	virtual ~Location() = default;

	const std::string& get_name() const
	{	return name; }

	/** Swap connection object with another location */
	void swap_connection( Location& loc );

	virtual void request_location( Location::ptr loc )
	{	emit_request_location(loc); }

	slot_connection on_location_request( const sig_location_slot& slot ) const
	{	return emit_request_location.connect( slot ); }


protected:
	void send_fail( ErrorCodes code , const std::string& msg = "" );
	void send_fail( id_t  id , ErrorCodes code , const std::string& msg = "" );

	void die()
	{
		if( connection )
			connection->close();
		sig_conn.disconnect();
		connection = NULL;
	}

	/** returns true if line was fully processed (i.e. caller should not attempt to perform any additional actions) */
	virtual bool parse_line( const std::string& line );

	void write_line( const std::string& line );

	mutable sig_location emit_request_location;

	id_t get_cmd_id() const;
	std::string get_cmd_name() const;
	std::string get_cmd_data() const;

private:
	void init_connection();

	std::string name;
	Connection* connection;

	boost::signals2::scoped_connection sig_conn;

	id_t cmd_id{};
	std::string cmd_name{};
	std::string cmd_data{};
};

#endif /* end of include guard: __CONNECTIONS_CONNECTION_H__ */

